package cn.shengchao.controler.ai;

import cn.shengchao.controler.ai.request.GetStudyCalendarRequest;
import cn.shengchao.controler.ai.request.GetStudyDaysRequest;
import cn.shengchao.controler.ai.response.ApiResponse;
import cn.shengchao.controler.ai.response.KnowledgePointStudyDayVO;
import cn.shengchao.examstar.ai.application.dto.StudyCalendarDTO;
import cn.shengchao.examstar.ai.application.dto.StudyDayDTO;
import cn.shengchao.examstar.ai.application.service.AiStudyDayService;
import cn.shengchao.examstar.knowledge.domain.entity.KnowledgePoint;
import cn.shengchao.examstar.knowledge.shared.service.KnowledgePointSharedService;
import cn.shengchao.util.helper.LoginHelper;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 学习日程控制器
 * 处理学习日程相关的HTTP请求
 */
@RestController
@Slf4j
@CrossOrigin("${project.cross-origin}")
@RequestMapping("/api/${project.version}/studyDays")
public class StudyDayController {

    @Autowired
    private AiStudyDayService aiStudyDayService;

    @Autowired
    private KnowledgePointSharedService knowledgePointSharedService;

    /**
     * 获取指定日期范围内的学习日程
     *
     * @param request 请求参数
     * @return 学习日程列表
     */
    @GetMapping
    @Operation(summary = "获取指定日期范围内的学习日程")
    public List<StudyDayDTO> getStudyDays(@Valid GetStudyDaysRequest request) {
        log.info("获取学习日程请求: startDate={}, endDate={}, studyPlanId={}",
                request.getStartDate(), request.getEndDate(), request.getStudyPlanId());

        Long userId = LoginHelper.getUserId();

        return aiStudyDayService.getStudyDays(
                userId,
                request.getStartDate(),
                request.getEndDate(),
                request.getStudyPlanId()
        );
    }

    /**
     * 获取当日学习计划
     *
     * @return 根知识点下包含所有学习日程的列表
     */
    @GetMapping("/day")
    @Operation(summary = "获取当日学习计划，所有学习日程挂在根知识点下")
    public ApiResponse<List<KnowledgePointStudyDayVO>> getTodayStudyDays(@RequestParam String date, @RequestParam Long studyPlanId) {
        LocalDate localDate = LocalDate.parse(date);
        log.info("获取当日学习计划: date={}, studyPlanId={}", localDate, studyPlanId);

        Long userId = LoginHelper.getUserId();
        List<StudyDayDTO> studyDays = aiStudyDayService.getStudyDays(userId, localDate, localDate, studyPlanId);

        if (studyDays == null || studyDays.isEmpty()) {
            return ApiResponse.success(Collections.emptyList());
        }

        // 1. 按知识点ID对学习日程进行分组，以便高效查找
        Map<Long, List<StudyDayDTO>> studyDaysByKpId = studyDays.stream().filter(studyDayDTO -> !studyDayDTO.getKnowledgePointId().equals("null"))
                .collect(Collectors.groupingBy(sd -> Long.valueOf(sd.getKnowledgePointId())));

        // 2. 获取所有相关学习日程的父知识点
        // 注意：此处假设 getKnowledgePointsByIds 依据原始实现逻辑，返回的是所提供ID的父知识点
        List<KnowledgePoint> parentKnowledgePoints = knowledgePointSharedService.getKnowledgePointsByIds(new ArrayList<>(studyDaysByKpId.keySet()));

        if (parentKnowledgePoints == null || parentKnowledgePoints.isEmpty()) {
            return ApiResponse.success(Collections.emptyList());
        }

        // 3. 构建结果VO列表
        List<KnowledgePointStudyDayVO> result = parentKnowledgePoints.stream()
                .map(parentKp -> {
                    KnowledgePointStudyDayVO kpVO = KnowledgePointStudyDayVO.fromKnowledgePoint(parentKp);

                    List<KnowledgePoint> children = parentKp.getChildren();
                    List<StudyDayDTO> associatedStudyDays = (children == null || children.isEmpty())
                            ? Collections.emptyList()
                            : children.stream()
                            .map(KnowledgePoint::getId)
                            .flatMap(childId -> studyDaysByKpId.getOrDefault(childId, Collections.emptyList()).stream())
                            .collect(Collectors.toList());
                    if (associatedStudyDays.isEmpty()) {
                        associatedStudyDays = studyDaysByKpId.getOrDefault(parentKp.getId(), Collections.emptyList());
                    }
                    kpVO.setStudyDays(associatedStudyDays);
                    return kpVO;
                })
                .collect(Collectors.toList());

        return ApiResponse.success(result);
    }

    /**
     * 获取学习日历
     *
     * @param request 请求参数
     * @return 学习日历
     */
    @GetMapping("/calendar")
    @Operation(summary = "获取学习日历")
    public ApiResponse<StudyCalendarDTO> getStudyCalendar(@Valid GetStudyCalendarRequest request) {
        log.info("获取学习日历请求: yearMonth={}, studyPlanId={}",
                request.getYearMonth(), request.getStudyPlanId());

        Long userId = LoginHelper.getUserId();
        StudyCalendarDTO result = aiStudyDayService.getStudyCalendar(
                userId,
                request.getYearMonth(),
                request.getStudyPlanId()
        );

        return ApiResponse.success(result);
    }

    /**
     * 获取本月学习日历
     *
     * @return 本月学习日历
     */
    @GetMapping("/calendar/current")
    @Operation(summary = "获取本月学习日历")
    public StudyCalendarDTO getCurrentMonthCalendar() {
        String currentYearMonth = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"));
        log.info("获取本月学习日历请求: yearMonth={}", currentYearMonth);

        Long userId = LoginHelper.getUserId();
        return aiStudyDayService.getStudyCalendar(userId, currentYearMonth, null);
    }

    /**
     * 标记学习日程为已完成
     *
     * @param id 学习日程ID
     * @return 更新后的学习日程
     */
    @PostMapping("/{id}/complete")
    @Operation(summary = "标记学习日程为已完成")
    public ApiResponse<StudyDayDTO> completeStudyDay(@PathVariable Long id) {
        log.info("标记学习日程为已完成请求: id={}", id);

        StudyDayDTO result = aiStudyDayService.completeStudyDay(id);

        return ApiResponse.success(result);
    }
}
 